<?php

namespace App\Api\Controllers\CustomerApplets;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use App\Api\Controllers\CustomerApplets\BaseController;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;

use Alipayopen\Sdk\AopClient;
use Alipayopen\Sdk\Request\AlipayMarketingCardTemplateCreateRequest;

use Alipayopen\Sdk\Request\AlipayMarketingCardFormtemplateSetRequest;
use Alipayopen\Sdk\Request\AlipayMarketingCardActivateurlApplyRequest;
use Alipayopen\Sdk\Request\AlipayMarketingCardOpenRequest;
use Alipayopen\Sdk\Request\AlipaySystemOauthTokenRequest;

use Alipayopen2019\AopClient as AopClient2019;
use Alipayopen2019\Request\AlipayOfflineMaterialImageUploadRequest;

class UserAliPayMembershipCardController extends BaseController
{
    /**
     * 支付宝会员卡上传的图片，在支付宝平台上
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function aliPayOfflineMaterialImageUpload(Request $request){

        $requestAllData = $request->all();

        if(isset($requestAllData['app_id']) && !empty($requestAllData['app_id'])){
            $appletsInfo = DB::table("customerapplets_authorize_appids")->where(['applet_type' => 2,'AuthorizerAppid' => $requestAllData['app_id']])->first();

            if(empty($appletsInfo)){
                return $this->responseDataJson(202,"该小程序暂未授权");
            }

            $authorizeAppId = [
                't_appid' => $appletsInfo->t_appid,
                'AuthorizationCode' => $appletsInfo->AuthorizationCode,
            ];
        }else{
            if(!isset($requestAllData['store_id']) || empty($requestAllData['store_id'])){
                return $this->responseDataJson(202,"门店id参数不可为空");
            }

            $storeInfo = DB::table("merchant_store_appid_secrets")->where(['store_id' => $requestAllData['store_id']])->first();

            if(empty($storeInfo)){
                return $this->responseDataJson(202,"该门店appid信息不存在");
            }

            if(empty($storeInfo->alipay_appid)){
                return $this->responseDataJson(202,"请先完善该门店支付宝小程序信息");
            }

            $authorizeAppId = $this->getAuthorizeAppId($storeInfo->alipay_appid);
            if(empty($authorizeAppId['t_appid'])){
                return $this->responseDataJson(202,"请先完成该小程序在支付宝第三方应用平台上进行授权");
            }
        }

        try {

            $file = $_FILES['file'];

            $imageName = explode('.', $file['name']);

            $suffix = $imageName[count($imageName) - 1];

            $uploadPath = 'upload/images/';

            if (!is_dir($uploadPath)) {
                mkdir($uploadPath, 0777, true);
            }

            $fileNamePrev = time() . rand(1, 10000);

            $fileName = basename($fileNamePrev. '.' . $suffix);

            $uploadFilePath = $uploadPath . $fileName; //存放图片路径

            $path = env("APP_URL")."/".$uploadFilePath;
            //转换成服务器的绝对路径
            $file_path = str_replace(env('APP_URL'), public_path(), $path);

            if (move_uploaded_file($file['tmp_name'], $uploadFilePath)) { //存放图片到本地

                $aop = new AopClient2019();
                $aop->gatewayUrl            = 'https://openapi.alipay.com/gateway.do';
                $aop->appId                 = $authorizeAppId['t_appid'];
                $aop->method                = "alipay.offline.material.image.upload";
                $aop->charset               = "utf-8";
                $aop->timestamp             = date("Y-m-d H:i:s",time());
                $aop->rsaPrivateKey         = $this->rsaPrivateKey;
                $aop->alipayrsaPublicKey    = $this->rsaPublicKey;
                $aop->apiVersion            = '1.0';
                $aop->signType              = 'RSA2';
                $aop->postCharset           = 'utf-8';
                $aop->format                = 'json';

                $request = new AlipayOfflineMaterialImageUploadRequest();
                $request->setImageType($suffix);
                $request->setImageName($fileNamePrev);
                $request->setImageContent("@".$uploadFilePath);
                $result = $aop->execute($request,null,$authorizeAppId['AuthorizationCode']);
                $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
                $resultCode = $result->$responseNode->code;
                if(!empty($resultCode) && $resultCode == 10000){
                    $image_id  = $result->$responseNode->image_id;
                    $image_url = $result->$responseNode->image_url;
                    return $this->responseDataJson(200,"上传成功",['image_id' => $image_id,'aliPay_image_url' => $image_url,'image_url' => $path,'image_path'=>$uploadFilePath]);
                } else {
                    return $this->responseDataJson(202,$result->$responseNode->code.'|'.$result->$responseNode->msg.'|'.$result->$responseNode->sub_code.'|'.$result->$responseNode->sub_msg);
                }
            } else {
                return $this->responseDataJson(202,"图片上传失败");
            }

        }catch (\Exception $e){
            return $this->responseDataJson(202,$e->getMessage());
        }

    }

    /**
     * 创建会员卡（支付宝）
     * 主要是针对于商户端进行创建
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function userAliPayCreateMemberCard(Request $request)
    {
        $requestAllData = $request->all();

        if(!isset($requestAllData['store_id']) || empty($requestAllData['store_id'])){
            return $this->responseDataJson(202,"门店id参数不可为空");
        }

        if(!isset($requestAllData['logo_id']) || empty($requestAllData['logo_id'])){
            return $this->responseDataJson(202,"门店logo不可为空");
        }

        if(!isset($requestAllData['background_id']) || empty($requestAllData['background_id'])){
            return $this->responseDataJson(202,"门店背景图不可为空");
        }

        $storeNameInfo = DB::table("stores")->select("merchant_id","store_name","store_short_name","people_phone","people")->where(['store_id' => $requestAllData['store_id']])->first();

        if(empty($storeNameInfo)){
            return $this->responseDataJson(202,"该门店信息不存在");
        }
        if(empty($storeNameInfo->store_name) && empty($storeNameInfo->store_short_name)){
            return $this->responseDataJson(202,"请先完善该门店名称信息");
        }
        if(empty($storeNameInfo->people_phone) && empty($storeNameInfo->people)){
            return $this->responseDataJson(202,"请先完善该门店联系人姓名和手机号信息");
        }

        $storeInfo = DB::table("merchant_store_appid_secrets")->where(['store_id' => $requestAllData['store_id']])->first();

        if(empty($storeInfo)){
            return $this->responseDataJson(202,"该门店appid信息不存在");
        }
        if(empty($storeInfo->alipay_appid)){
            return $this->responseDataJson(202,"请先完善该门店支付宝小程序信息");
        }
        $authorizeAppId = $this->getAuthorizeAppId($storeInfo->alipay_appid);
        if(empty($authorizeAppId['t_appid'])){
            return $this->responseDataJson(202,"请先完成该小程序在支付宝第三方应用平台上进行授权");
        }

        //先判断该门店是否可以创建会员卡
        $membership_card_lists = DB::table("membership_card_lists")->where(['store_id' =>$requestAllData['store_id'] , 'terminal_type' => $requestAllData['terminal_type']])->first();
        if(!empty($membership_card_lists)){
            return $this->responseDataJson(202, "该门店已经创建了会员卡，不可重复创建", "");
        }

        try {
            $aop = new AopClient();
            $aop->gatewayUrl            = 'https://openapi.alipay.com/gateway.do';
            $aop->appId                 = $authorizeAppId['t_appid'];
            $aop->method                = "alipay.marketing.card.template.create";
            $aop->charset               = "utf-8";
            $aop->timestamp             = date("Y-m-d H:i:s",time());
            $aop->rsaPrivateKey         = $this->rsaPrivateKey;
            $aop->alipayrsaPublicKey    = $this->rsaPublicKey;
            $aop->apiVersion            = '1.0';
            $aop->signType              = 'RSA2';
            $aop->postCharset           = 'utf-8';
            $aop->format                = 'json';

            $request = new AlipayMarketingCardTemplateCreateRequest ();

            $request_id = date("YmdHis").time().rand(1,10000);

            $request->setBizContent("{" .

                /** 请求ID，由开发者生成并保证唯一性  **/
                "\"request_id\":\"".$request_id."\"," .

                /** 卡类型为固定枚举类型，可选类型如下：OUT_MEMBER_CARD：外部权益卡  **/
                "\"card_type\":\"OUT_MEMBER_CARD\"," .

                /** 业务卡号前缀，由商户指定。支付宝业务卡号生成规则：biz_no_prefix(商户指定)卡号前缀 . biz_no_suffix(实时生成）卡号后缀  **/
                "\"biz_no_prefix\":\"HB\"," .

                /** 业务卡号后缀的长度，取值范围为[8,32]。biz_no_suffix_len一旦指定，在模板修改时不支持修改。  **/
                "\"biz_no_suffix_len\":\"12\"," .

                /** 卡包详情页面中展现出的卡码（可用于扫码核销），字段格式详见文档  **/
                "\"write_off_type\":\"qrcode\",".

                /** 模板样式信息  **/
                "\"template_style_info\":{".

                /** 钱包端显示名称  **/
                "\"card_show_name\":\"".$requestAllData['title']."\",".

                /** logo的图片ID，通过接口（alipay.offline.material.image.upload）上传图片，请优先使用商家LOGO  **/
                "\"logo_id\":\"".$requestAllData['logo_id']."\",".

                /** 背景图片Id，通过接口（alipay.offline.material.image.upload）上传图片，图片不得有圆角，不得拉伸变形  **/
                "\"background_id\":\"".$requestAllData['background_id']."\",".

                /** 字体颜色（非背景色），只影响卡详情中部信息区域字体颜色  **/
                "\"bg_color\":\"rgb(55,112,179)\"" .

                "},".

                /** 栏位信息  **/
                "\"column_info_list\":[".

                /** 设置一个自定义栏位  **/
                /** 自定义栏位：行为由商户定义，自定义Code码（只要无重复）  **/
                "{\"code\": \"BHG\",".

                /** 栏目的标题  **/
                "\"title\": \"联系商家\",".

                /** 卡包详情页面，卡栏位右边展现的值  **/
                "\"value\": \"".$storeNameInfo->people_phone."\",".

                /** 栏位打开方式，1、openNative：打开二级页面，展现 more中descs；2、openWeb：打开URL；3、staticinfo：静态信息  **/
                "\"operate_type\": \"staticinfo\"".
                "},".

                /** 设置一个标准积分栏位  **/

                /** 准栏位：行为由支付宝统一定，同时已经分配标准Code：BALANCE：会员卡余额；POINT：积分；LEVEL：等级；TELEPHONE：联系方式  **/
                "{\"code\": \"POINT\",".

                /** 栏目的标题  **/
                "\"title\": \"积分\",".

                /** 积分、余额等栏位无需设置value，字段规则由field_rule_list控制  **/
                //"\"value\": \"100\",".

                /** 栏位打开方式，1、openNative：打开二级页面，展现 more中descs；2、openWeb：打开URL；3、staticinfo：静态信息  **/
                "\"operate_type\": \"staticinfo\"".
                "}".

                "],".

                /** 字段规则列表,标准栏位需要设置栏位信息的字段生成规则  **/
                /** 设置积分栏位的积分生成规则  **/
                "\"field_rule_list\": [".

                /** 字段名称，现在支持如下几个Key（暂不支持自定义）；Balance：金额；Point：整数；Level：任意字符串；OpenDate：开卡日期；ValidDate：过期日期  **/
                "{ \"field_name\": \"Point\",".

                /** 规则名，ASSIGN_FROM_REQUEST表示该栏位的值从会员卡开卡接口中获取，会员卡开卡接口的card_info中获取对应参数值，其他值详见文档  **/
                "\"rule_name\": \"ASSIGN_FROM_REQUEST\",".

                /** 根据rule_name，采取相应取值策略，详见文档说明  **/
                "\"rule_value\": \"Point\"".
                "}".
                "]".
                "}");

            $result       = $aop->execute($request,null,$authorizeAppId['AuthorizationCode']);
            $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
            $resultCode   = $result->$responseNode->code;
            if(!empty($resultCode)&&$resultCode == 10000){
                $template_id = $result->$responseNode->template_id;

                //第二步：配置开卡表单
                $aop->method = "alipay.marketing.card.formtemplate.set";
                $requestCard = new AlipayMarketingCardFormtemplateSetRequest();
                $requestCard->setBizContent("{" .
                    "\"template_id\":\"".$template_id."\"," .
                    "\"fields\":{" .
                    "\"required\":\"{\\\"common_fields\\\":[\\\"OPEN_FORM_FIELD_MOBILE\\\"]}\"" .
                    "}" .
                    "}");
                $resultCard = $aop->execute($requestCard,null,$authorizeAppId['AuthorizationCode']);
                $responseNodeCard = str_replace(".", "_", $requestCard->getApiMethodName()) . "_response";
                $resultCodeCard = $resultCard->$responseNodeCard->code;
                if(!empty($resultCodeCard) && $resultCodeCard == 10000){

                    ////第三步：配置开卡表单成功，进行获取获取会员卡领卡投放链接
                    $aop->method = "alipay.marketing.card.activateurl.apply";
                    $requestCardUrl = new AlipayMarketingCardActivateurlApplyRequest();
                    $requestCardUrl->setBizContent("{" .
                        "\"template_id\":\"".$template_id."\"," .
                        "\"out_string\":\"aliPayMemberCard\"," .
                        "\"callback\":\"".config('api.aliPayCallBackUrl')."\"" .
                        "}");
                    $resultCardUrl = $aop->execute($requestCardUrl,null,$authorizeAppId['AuthorizationCode']);
                    $responseNodeCardUrl = str_replace(".", "_", $requestCardUrl->getApiMethodName()) . "_response";
                    $resultCodeCardUrl = $resultCardUrl->$responseNodeCardUrl->code;
                    if(!empty($resultCodeCardUrl) && $resultCodeCardUrl == 10000){

                        $apply_card_url = $resultCardUrl->$responseNodeCardUrl->apply_card_url;
                        $apply_card_url = urldecode($apply_card_url);

                        //存储会员卡数据
                        DB::table("membership_card_lists")->insert([
                            'store_id'      => $requestAllData['store_id'],
                            'terminal_type' => "aliPay",
                            'card_code'     => time(),
                            'card_id'       => $template_id,
                            'status'        => 1,
                            'card_activateurl_apply' => $apply_card_url,
                            'created_at'    => date("Y-m-d H:i:s",time()),
                            'updated_at'    => date("Y-m-d H:i:s",time()),
                        ]);

                        return $this->responseDataJson(200,"创建成功",['template_id' => $template_id,'card_activateurl_apply' => $apply_card_url]);
                    }else{
                        return $this->responseDataJson(202,$resultCardUrl->$responseNodeCardUrl->msg);
                    }

                } else {
                    return $this->responseDataJson(202,$resultCard->$responseNodeCard->msg);
                }

            } else {
                return $this->responseDataJson(202,$result->$responseNode->msg);
            }
        }catch (\Exception $e){
            return $this->responseDataJson(202,$e->getMessage());
        }
    }

    /**
     * 测试 商户对用户进行 会员卡开卡
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function aliPayMarketingCardOpenTest(Request $request){
        $requestAllData = $request->all();
        $result = $this->aliPayMarketingCardOpen($requestAllData);
        if($result['status'] == 200){
            return $this->responseDataJson(200,$result['message'],$result['data']);
        }else{
            return $this->responseDataJson(202,$result['message']);
        }
    }

    /**
     * (封装)商户对用户进行 会员卡开卡
     * @param $requestAllData
     * @return array
     */
    public function aliPayMarketingCardOpen($requestAllData){

        $storeInfo = DB::table("merchant_store_appid_secrets")->where(['store_id' => $requestAllData['store_id']])->first();

        $storeNameInfo = DB::table("stores")->select("merchant_id","store_name","store_short_name")->where(['store_id' => $requestAllData['store_id']])->first();

        if(empty($storeNameInfo)){
            return ['status' => 202,'message' => '该门店信息不存在'];
        }
        if(empty($storeNameInfo->store_name) && empty($storeNameInfo->store_short_name)){
            return ['status' => 202,'message' => '请先完善该门店名称信息'];
        }

        if(empty($storeInfo)){
            return ['status' => 202,'message' => '门店信息不存在'];
        }
        if(empty($storeInfo->alipay_appid)){
            return ['status' => 202,'message' => '请先完善该门店支付宝小程序信息'];
        }

        $aliPayUserInfo = DB::table("customerapplets_user_alipays")->where(['user_id' => $requestAllData['user_id']])->first();
        if(empty($aliPayUserInfo)){
            return ['status' => 202,'message' => 'user_aliPays：用户信息不存在'];
        }
        if(empty($aliPayUserInfo->alipay_user_id)){
            return ['status' => 202,'message' => 'user_aliPays：请先授权该小程序'];
        }

        $authorizeAppId = $this->getAuthorizeAppId($storeInfo->alipay_appid);
        if(empty($authorizeAppId['t_appid'])){
            return ['status' => 202,'message' => 'user_aliPays：请先完成该小程序在支付宝第三方应用平台上进行授权'];
        }

        try {
            $aop = new AopClient();
            $aop->gatewayUrl            = 'https://openapi.alipay.com/gateway.do';
            $aop->appId                 = $authorizeAppId['t_appid'];
            $aop->method                = "alipay.marketing.card.open";
            $aop->charset               = "utf-8";
            $aop->timestamp             = date("Y-m-d H:i:s",time());
            $aop->rsaPrivateKey         = $this->rsaPrivateKey;
            $aop->alipayrsaPublicKey    = $this->rsaPublicKey;
            $aop->apiVersion            = '1.0';
            $aop->signType              = 'RSA2';
            $aop->postCharset           = 'utf-8';
            $aop->format                = 'json';

            //获取accessToken
            $requestToken = new AlipaySystemOauthTokenRequest();
            $requestToken->setGrantType("authorization_code");
            $requestToken->setCode($requestAllData['code']);
            $resultToken = $aop->execute($requestToken,null,$authorizeAppId['AuthorizationCode']);
            $responseNodeToken = str_replace(".", "_", $requestToken->getApiMethodName()) . "_response";

            if(isset($resultToken->$responseNodeToken->access_token) && !empty($resultToken->$responseNodeToken->access_token)){
                $access_token   = $resultToken->$responseNodeToken->access_token;
                Log::info("开卡access_token：".$access_token);
                $alipay_user_id = $resultToken->$responseNodeToken->alipay_user_id;

                //进行开卡
                $aop->method = "alipay.marketing.card.open";
                $request     = new AlipayMarketingCardOpenRequest();
                $request_id  = date("YmdHis").time().rand(1,10000);
                $nowDate     = date("Y-m-d H:i:s",time());

                $request->setBizContent("{" .
                    "\"out_serial_no\":\"".$request_id."\"," .
                    "\"card_template_id\":\"".$requestAllData['card_id']."\"," .
                    "\"card_user_info\":{" .
                    "\"user_uni_id\":\"".$aliPayUserInfo->alipay_user_id."\"," .
                    "\"user_uni_id_type\":\"UID\"" .
                    "}," .
                    "\"card_ext_info\":{" .
                    "\"biz_card_no\":\"BCN".$request_id."\"," .
                    "\"external_card_no\":\"ECN".$request_id."\"," .
                    "\"open_date\":\"".$nowDate."\"," .
                    "\"valid_date\":\"2050-01-01 01:00:00\"," .
                    "\"level\":\"VIP1\"," .
                    "\"front_text_list\":[{" .
                    "\"label\":\"餐饮\"," .
                    "\"value\":\"店面\"" .
                    "}]," .
                    "\"front_image_id\":\"\"" .
                    "}," .
                    "\"open_card_channel\":\"\"," .
                    "\"open_card_channel_id\":\"\"" .
                    "}");
                $result = $aop->execute ($request,$access_token,$authorizeAppId['AuthorizationCode']);
                $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
                $resultCode   = $result->$responseNode->code;
                Log::info("开卡code：".$resultCode);
                if(!empty($resultCode) && $resultCode == 10000){

                    $card_info = "";

                    if(isset($result->$responseNode->card_info) && !empty($result->$responseNode->card_info)){
                        $card_info = $result->$responseNode->card_info;
                        Log::info("开卡数据：".json_encode($card_info));
                        $card_info = json_encode($card_info);
                    }

                    return ['status' => 200,'message' => '开卡成功','data' => $card_info];
                } else {
                    Log::info("开卡sub_code：".$result->$responseNode->sub_code);
                    Log::info("开卡sub_msg：".$result->$responseNode->sub_msg);
                    return ['status' => 202,'message' => $result->$responseNode->msg];
                }

            }else{
                return ['status' => 202,'message' => $resultToken->$responseNodeToken->msg];
            }
        }catch (\Exception $e){
            return ['status' => 202,'message' => $e->getMessage()];
        }
    }

}
